/**********************************************************
 * File description:WLKService.cpp
 * Function:实验模板文件服务类
 * Current Version: 1.0.0
 * Author: 夏新宇
 * Date: 2022-10-24
 *  -----
 *  Copyright by bokun Software.
 **********************************************************/
#include "WLKService.h"

WLKService::WLKService(){

}

/*!
 * \brief 保存wlk实验模板文件
 *
 * \param QString filePath 保存文件路径
 *
 * \param WLKData wlkData WLKData类型的结构体，包含所需实验数据
 *
 *
 * Detail here!!!
 */
void WLKService::saveWLK(QString filePath, WLKData wlkData){
    LOG << "保存wlk实验模板文件";

    LOG << wlkData.experimentName << wlkData.experimentId << wlkData.startTime
        << wlkData.endTime
        << wlkData.reshiWendu
        << wlkData.type << wlkData.username << wlkData.encode
        << wlkData.divice_name << wlkData.device_id << wlkData.device_series
        << wlkData.canBi
        << wlkData.experimentRemarks << wlkData.plateRemarks;

    QFile *m_file = new QFile(filePath);
    if (m_file->open(QIODevice::WriteOnly)){
        QDataStream stream(m_file);
        stream << wlkData.experimentName << wlkData.experimentId << wlkData.startTime
               << wlkData.endTime
               << wlkData.reshiWendu
               << wlkData.type << wlkData.username << wlkData.encode
               << wlkData.divice_name << wlkData.device_id << wlkData.device_series
               << wlkData.canBi
               << wlkData.experimentRemarks << wlkData.plateRemarks;

        //序列化扩增程序数据
        LOG << "序列化扩增程序数据";
        QList<QHash<QString,QString>> stagesList = wlkData.procedureData.keys();
        for(int i = 0;i < stagesList.size();i ++){
            for(int j = i + 1;j < stagesList.size();j ++){
                int l = stagesList[i]["stage_order"].toInt();
                int k = stagesList[j]["stage_order"].toInt();
                if(l > k){
                    QHash<QString,QString> thash = stagesList[i];
                    stagesList[i] = stagesList[j];
                    stagesList[j] = thash;
                }
            }
        }

        QString stageSize = QString::number(stagesList.size());
        stream << stageSize;
        for(int i = 0;i < stagesList.size();i ++) stream << stagesList[i];
        for(int i = 0;i < stagesList.size();i ++){
            QString stepSize = QString::number(wlkData.procedureData[stagesList[i]].size()); //每个阶段对应的步骤数量
            stream << stepSize;
            for(int j = 0;j < stepSize.toInt();j ++){
                stream << wlkData.procedureData[stagesList[i]][j];
            }
        }
        //序列化反应板数据
        LOG << "序列化反应板耗材类型数据";
        stream << wlkData.reactionPlate.consumables;

        LOG << "序列化反应板样本数据";
        for(int i = 0;i < 96;i ++){
            wlkData.reactionPlate.sampleList[i].id = QString::number(i);
            stream << wlkData.reactionPlate.sampleList[i];
        }
        LOG << "序列化反应板靶基因数据";
        for(int i = 0;i < 96;i ++){
            for(int j = 0;j < 20;j ++){
                stream << wlkData.reactionPlate.targetList[i][j];
            }
        }
        LOG << "序列化荧光数据";
        QString yingGuangSize = QString::number(wlkData.yingGuangData.size());
        stream << yingGuangSize;
        for(int i = 0;i < yingGuangSize.toInt();i ++){
            QString yingGuangSubSize = QString::number(wlkData.yingGuangData[i].size());
            stream << yingGuangSubSize;
            for(int j = 0;j < yingGuangSubSize.toInt();j ++){
                stream << wlkData.yingGuangData[i][j];
            }
        }

        if(m_file->isOpen())
            m_file->close();
    }
}

/*!
 * \brief 加载wlk实验模板文件
 *
 * \param QString filePath wlk文件路径
 *
 * \return WLKData wlkData WLKData类型的结构体，包含所需实验数据
 *
 *
 * Detail here!!!
 */
tuple<WLKData,bool> WLKService::getWLKData(QString filePath){
    tuple<WLKData,bool> res;

    LOG << "反序列化";

    WLKData wlkData;
    QFile *m_file = new QFile(filePath);
    QHash<QHash<QString,QString>,QList<QHash<QString,QString>>> procedureData;
    try{
        if (m_file->open(QIODevice::ReadOnly)){
            QDataStream stream(m_file);

            stream >> wlkData.experimentName >> wlkData.experimentId >> wlkData.startTime
                   >> wlkData.endTime
                   >> wlkData.reshiWendu
                   >> wlkData.type >> wlkData.username >> wlkData.encode
                   >> wlkData.divice_name >> wlkData.device_id >> wlkData.device_series
                   >> wlkData.canBi
                   >> wlkData.experimentRemarks >> wlkData.plateRemarks;

            QString stageSize;
            stream >> stageSize;
            QList<QHash<QString,QString>> stagesList;
            for(int i = 0;i < stageSize.toInt();i ++){
                QHash<QString,QString> tHash;
                stream >> tHash;
                stagesList.append(tHash);
            }
            //            LOG << stagesList;
            for(int i = 0;i < stageSize.toInt();i ++){
                QList<QHash<QString,QString>> stepList;
                QString stepSize;
                stream >> stepSize;
                //            LOG << stepSize;
                for(int j = 0;j < stepSize.toInt();j ++){
                    QHash<QString,QString> tHash;
                    stream >> tHash;
                    stepList.append(tHash);
                }
                procedureData[stagesList[i]] = stepList;
            }
            //        LOG << procedureData;
            wlkData.procedureData = procedureData;

            stream >> wlkData.reactionPlate.consumables;

            for(int i = 0;i < 96;i ++){
                Sample sample;
                stream >> sample;
                wlkData.reactionPlate.sampleList[i] = sample;
            }


            for(int i = 0;i < 96;i ++){
                for(int j = 0;j < 20;j ++){
                    Target target;
                    stream >> target;
                    //                LOG << target.name;
                    wlkData.reactionPlate.targetList[i][j] = target;
                }
            }


            QList<QList<QHash<QString, QString>>> yingGuangData;
            QString yingGuangSize;
            stream >> yingGuangSize;
            for(int i = 0;i < yingGuangSize.toInt();i ++){
                QString yingGuangSubSize;
                stream >> yingGuangSubSize;
                QList<QHash<QString, QString>> tList;
                for(int j = 0;j < yingGuangSubSize.toInt();j ++){
                    QHash<QString, QString> qHash;
                    stream >> qHash;
                    tList.append(qHash);
                }
                yingGuangData.append(tList);
            }
            wlkData.yingGuangData = yingGuangData;
            if(m_file->isOpen())
                m_file->close();
        }

        LOG << wlkData.experimentName << wlkData.experimentId << wlkData.startTime
            << wlkData.endTime
            << wlkData.reshiWendu
            << wlkData.type << wlkData.username << wlkData.encode
            << wlkData.divice_name << wlkData.device_id << wlkData.device_series
            << wlkData.canBi
            << wlkData.experimentRemarks << wlkData.plateRemarks;

        res = make_tuple(wlkData,true);
    }catch(string s){
        res = make_tuple(wlkData,false);
        return res;
    }
    return res;
}


void WLKService::procedureDataPersistence(QString experimentId,QHash<QHash<QString,QString>,QList<QHash<QString,QString>>> procedureData){
    ProcedureService * procedureService = new ProcedureService();
    QList<QHash<QString,QString>> stageList = procedureData.keys();
    for(int i = 0;i < stageList.size();i ++){
        QList<QHash<QString,QString>> stepList = procedureData[stageList[i]];
        procedureService->insertStage(experimentId,stageList[i]["name"],
                stageList[i]["stage_order"],stageList[i]["cycle_number"],stepList);
    }
}
